package com.kefu.robot.controller;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kefu.chat.http.NlpClient;
import com.kefu.chat.http.RobotNearestParam;
import com.kefu.robot.vo.RobotSimilarVo;
import com.kefu.common.context.KefuContext;
import com.kefu.common.controller.AbstractBaseController;
import com.kefu.common.result.Result;
import com.kefu.common.result.ResultGenerator;
import com.kefu.common.util.Assert;
import com.kefu.common.vo.DeleteVo;
import com.kefu.common.vo.DetailVo;
import com.kefu.robot.model.RobotDoc;
import com.kefu.robot.model.RobotDocType;
import com.kefu.robot.service.RobotDocCommentService;
import com.kefu.robot.service.RobotDocService;
import com.kefu.robot.service.RobotDocTypeService;
import com.kefu.robot.vo.RobotCopyDocVo;
import com.kefu.robot.vo.RobotDocInsertVo;
import com.kefu.robot.vo.RobotDocSearchVo;
import com.kefu.robot.vo.RobotDocUpdateBatchVo;
import com.kefu.robot.vo.RobotDocUpdateVo;
import com.kefu.robot.vo.RobotNearestResultVo;
import com.kefu.robot.vo.RobotNearestResultVo.Regex;
import com.kefu.robot.vo.RobotNearestRobotParam;
import com.kefu.robot.vo.RobotSimilarParamVo;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;


@Api(tags = "知识词条")
@RestController
@RequestMapping("robot/doc")
public class RobotDocController extends AbstractBaseController {
    @Resource
    private RobotDocCommentService commentService;
    @Autowired
    private RobotDocService robotDocService;
    @Autowired
    private RobotDocTypeService robotDocTypeService;

    //相似问题查询阈值
    @Value("${kefu.robot.similar.add.threshold:0.8}")
    private Float similarAddThreshold;
    //相似问题查询阈值
    @Value("${kefu.robot.similar.search.threshold:0.72}")
    private Float similarSearchThreshold;
    //相似问题查询条数
    @Value("${kefu.robot.similar.search.size:5}")
    private int similarSearchSize;

    @Autowired
    NlpClient nlpClient;

    @PostMapping("/add")
    @ApiOperation(value = "新增知识词条", notes = "新增知识词条")
    public Result<String> add(@Validated @RequestBody RobotDocInsertVo robotDocVo) {
        logger.info("新增知识词条:{}", robotDocVo);
//        RobotNearestRobotParam ask=new RobotNearestRobotParam();
//    	ask.setQuestion(robotDocVo.getDocQuestion());
//    	ask.setRobotNo(robotDocVo.getRobotNo());
//    	ask.setTenantId(KefuContext.getTid());
//    	ask.setThreshold(similarAddThreshold);
//    	ask.setSize(1);
//    	List<RobotSimilarVo> result=nlpClient.nearestRobot(ask)
//		    				.stream()
//		    				.filter(doc->!doc.getDocId().equals(robotDocVo.getDocId()))
//		    				.collect(Collectors.toList());
//    	Assert.isNotEmpty(result, "存在相同的词条");
        return ResultGenerator.genSuccessResult(robotDocService.addDoc(robotDocVo));
    }

    @PostMapping("/copyDoc")
    @ApiOperation(value = "复制知识词条", notes = "复制知识词条")
    public Result<String> copyDoc(@RequestBody RobotCopyDocVo vo) {
        logger.info("复制知识词条:{},{}", KefuContext.getKefuContext(), vo);
        robotDocService.copyDoc(vo);
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/importDoc")
    @ApiOperation(value = "导入知识词条", notes = "导入知识词条")
    public Result<String> importDoc(MultipartFile file, Integer robotNo) throws IOException {
        logger.info("导入知识词条:{},{}", KefuContext.getKefuContext(), robotNo);
        Assert.isNull(robotNo, "请选择导入的机器人信息！");
        return ResultGenerator.genSuccessResult(robotDocService.importDoc(file.getInputStream(), robotNo));
    }

    @PostMapping("/delete")
    @ApiOperation(value = "删除知识词条", notes = "删除知识词条，多个逗号分隔")
    public Result<String> delete(@Validated @RequestBody DeleteVo delete) {
        logger.info("删除知识词条，客服id: {}, 词条id: {}", KefuContext.getUid(), delete);
        for (String id : delete.getId().split(",")) {
            robotDocService.delDoc(id);
        }
        return ResultGenerator.genSuccessResult();
    }

    @PostMapping("/update")
    @ApiOperation(value = "修改知识词条", notes = "修改知识词条")
    public Result<String> update(@Validated @RequestBody RobotDocUpdateVo robotDocVo) {
        logger.info("修改知识词条:{}", robotDocVo);
        RobotDoc robotDoc = robotDocService.findById(robotDocVo.getDocId());
        Assert.isNull(robotDoc, "词条不存在");
        //TODO 暂时
//        RobotNearestRobotParam ask = new RobotNearestRobotParam();
//    	ask.setRobotNo(robotDoc.getRobotNo());
//        ask.setTenantId(KefuContext.getTid());
//        ask.setThreshold(similarAddThreshold);
//        ask.setQuestion(StrUtil.isBlank(robotDocVo.getDocQuestion()) ?
//                robotDoc.getDocQuestion() : robotDocVo.getDocQuestion());
//        ask.setSize(1);
//    	List<RobotSimilarVo> result = nlpClient.nearestRobot(ask)
//		    				.stream()
//		    				.filter(doc->!doc.getDocId().equals(robotDocVo.getDocId()))
//		    				.collect(Collectors.toList());
//    	Assert.isNotEmpty(result, "存在相同的词条");
        return ResultGenerator.genSuccessResult(robotDocService.updateDoc(robotDocVo));
    }

    @PostMapping("/updateDocBatch")
    @ApiOperation(value = "批量修改知识词条")
    public Result<String> updateDocBatch(@Validated @RequestBody RobotDocUpdateBatchVo robotDocVo) {
        logger.info("批量修改知识词条:{}", robotDocVo);
        return ResultGenerator.genSuccessResult(robotDocService.updateDocBatch(robotDocVo));
    }

    @PostMapping("/detail")
    @ApiOperation(value = "知识词条详情", notes = "知识词条详情")
    public Result<RobotDoc> detail(@Validated @RequestBody DetailVo detail) {
        RobotDoc robotDoc = robotDocService.findById(detail.getId());
        if (!"0".equals(robotDoc.getDocTypeId())) {
            RobotDocType docType = robotDocTypeService.findById(robotDoc.getDocTypeId());
            robotDoc.setDocTypeName(docType == null ? null : docType.getName());
        }
        robotDoc.setSimilarQuestions(robotDocService.getSimilarQuestions(detail.getId()));
        robotDoc.setLinkQuestions(robotDocService.getLinkQuestions(detail.getId()));
        return ResultGenerator.genSuccessResult(robotDoc);
    }

    @PostMapping("/list")
    @ApiOperation(value = "查询知识词条", notes = "查询知识词条")
    public Result<Page<RobotDoc>> list(@Validated @RequestBody RobotDocSearchVo search) {

        Page<RobotDoc> list=robotDocService.searchList(search);

        return ResultGenerator.genSuccessResult(list);
    }

    @PostMapping("/exportDoc")
    @ApiOperation(value = "导出知识词条", notes = "根据条件不分页一次性导出，至少需要传递一个robotNo")
    public void exportDoc(@Validated @RequestBody RobotDocSearchVo search, HttpServletResponse response) throws IOException {

        List<Map<String, Object>> mapList = robotDocService.exportDoc(search);
        excelWriter(mapList, response);
    }

    @PostMapping("/nearest")
    @ApiOperation(value = "相似度测试")
    public Result<RobotNearestResultVo> nearest(@RequestBody RobotNearestParam param) {
        param.setSize(param.getQuestionList().size());
        List<Map.Entry<Integer, Float>> nearsetResult = nlpClient.nearest(param);
        RobotNearestResultVo result = RobotNearestResultVo.builder()
                .question(param.getQuestion())
                .matcherList(nearsetResult == null ? null : nearsetResult.stream()
                        .map(entry -> Regex.builder()
                                .regex(param.getQuestionList().get(entry.getKey()))
                                .score(entry.getValue())
                                .build())
                        .collect(Collectors.toList()))
                .build();
        return ResultGenerator.genSuccessResult(result);
    }

    @PostMapping("/similarList")
    @ApiOperation(value = "相似度列表", notes = "查询问题的相似问题")
    public Result<List<RobotSimilarVo>> similarList(@RequestBody RobotSimilarParamVo param) {

        RobotNearestRobotParam ask = new RobotNearestRobotParam();
        ask.setQuestion(param.getQuestion());
        ask.setRobotNo(param.getRobotNo());
        ask.setTenantId(KefuContext.getTid());
        ask.setThreshold(similarSearchThreshold);
        ask.setSize(similarSearchSize);
        List<RobotSimilarVo> result = nlpClient.nearestRobot(ask)
                .stream()
                .filter(doc -> !doc.getDocId().equals(param.getDocId()))
                .collect(Collectors.toList());

        return ResultGenerator.genSuccessResult(result);
    }
}
